package utils

import "math/big"

// 计算n的阶乘
func Factorial(n uint64) (res *big.Int) {
	res = big.NewInt(1)

	// 0! = 1
	if n == 0 {
		return
	}

	res.SetUint64(n)
	for num := n - 1; num > 0; num-- {
		temp := big.NewInt(0)
		temp.SetUint64(num)
		res.Mul(res, temp)
	}

	return
}

// 计算排列A(n, m) n:元素总数 m:参与排列的元素个数
func Arrangement(n, m uint64) (res *big.Int) {
	// 必须满足 n >= m
	if m > n {
		res = big.NewInt(0)
		return
	}

	// n! / (n - m)!
	nF := Factorial(n)
	res = nF.Div(nF, Factorial(n-m))

	return
}

// 计算组合C(n, m) n:元素总数 m:参与组合的元素个数
func Combination(n, m uint64) (res *big.Int) {
	// 必须满足 n >= m
	if m > n {
		res = big.NewInt(0)
		return
	}

	// A(n, m) / m!
	a := Arrangement(n, m)
	res = a.Div(a, Factorial(m))

	return
}
